package com.mcj.quartz.service;

import com.mcj.quartz.entity.MyQuartzJobPO;
import com.mcj.quartz.repository.MyQuartzJobRepository;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author : maichaojiu
 * @Descirption :
 * @date : 2018/4/8
 */
@Service
public class QuartzServiceImpl implements QuartzService {

    private static final Logger logger =  LoggerFactory.getLogger(QuartzServiceImpl.class);
    @Autowired
    private Scheduler scheduler;

    @Autowired
    private MyQuartzJobRepository myQuartzJobRepository;

    /**
     * @Author : maichaojiu
     * @Description : 刷新所有定时任务
     * Date : 2018/4/8 11:41
     */
    public void refreshJob() {
        try {
            //查询出数据库中所有的定时任务
            List<MyQuartzJobPO> jobList = myQuartzJobRepository.findAll();
            if(null != jobList && jobList.size() > 0){
                for(MyQuartzJobPO po : jobList){
                    Integer status = po.getStatus(); //该任务触发器目前的状态
                    TriggerKey triggerKey = TriggerKey.triggerKey(po.getJobName(), po.getJobGroup());
                    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
                    //说明本条任务还没有添加到quartz中
                    if (null == trigger) {
                        if(0 == status){ //如果是禁用，则不用创建触发器
                            continue;
                        }

                        this.add(po.getJobName(), po.getJobGroup(), po.getCron());

                    } else {  //说明查出来的这条任务，已经设置到quartz中了
                        // Trigger已存在，先判断是否需要删除，如果不需要，再判定是否时间有变化
                        if(0 == status){ //如果是禁用，从quartz中删除这条任务
                            JobKey jobKey = JobKey.jobKey(po.getJobName(), po.getJobGroup());
                            scheduler.deleteJob(jobKey);
                            continue;
                        }
                        String searchCron = po.getCron(); //获取数据库的
                        String currentCron = trigger.getCronExpression();
                        if(!searchCron.equals(currentCron)){  //说明该任务有变化，需要更新quartz中的对应的记录
                            //表达式调度构建器
                            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);

                            //按新的cronExpression表达式重新构建trigger
                            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                                    .withSchedule(scheduleBuilder).build();

                            //按新的trigger重新设置job执行
                            scheduler.rescheduleJob(triggerKey, trigger);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("定时任务每日刷新触发器任务异常，在ScheduleTriggerServiceImpl的方法refreshTrigger中，异常信息：",e);
        }
    }

    /**
     * @Author : maichaojiu
     * @Description : 添加定时任务
     * Date : 2018/4/8 15:11
     */
    public boolean add(String name, String group, String cron){
        try {
            JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(name))
                    .withIdentity(name, group).build();

            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);

            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group).withSchedule(scheduleBuilder).build();

            //把trigger和jobDetail注入到调度器
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e){
            System.out.println(e);
        }
        return true;
    }

    /**
     * @Author : maichaojiu
     * @Description : 启动定时任务
     * Date : 2018/4/8 11:45
     */
    public boolean start(String name, String group, String cron) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(name, group);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if(null == trigger){
                this.add(name, group, cron);
            }else{
                this.modify(name, group, cron);
            }
        } catch (Exception e){
            System.out.println(e);
        }
        return true;
    }

    /**
     * @Author : maichaojiu
     * @Description : 停止定时任务
     * Date : 2018/4/8 11:46
     */
    public boolean stop(String name, String group) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(name, group);
            boolean b = scheduler.unscheduleJob(triggerKey);//移除触发器
        } catch (Exception e){
            System.out.println(e);
        }
        return true;
    }

    /**
     * @Author : maichaojiu
     * @Description : 立即执行一次定时任务
     * Date : 2018/4/8 11:46
     */
    public boolean execute(String name, String group) {
        try {
            JobKey jobKey = JobKey.jobKey(name, group);
            //判断任务调度器中否存在该任务
            TriggerKey triggerKey = TriggerKey.triggerKey(name, group);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if(null != trigger){
                scheduler.triggerJob(jobKey);
            }else{
                //利用反射来执行方法
                Class<?> class1 = Class.forName(name);
                Object obj = class1.newInstance();
                Job job = (Job) obj;
                job.execute(null);
            }
        } catch (Exception e){
            System.out.println(e);
        }
        return true;
    }

    /**
     * @Author : maichaojiu
     * @Description : 删除定时任务
     * Date : 2018/4/8 11:47
     */
    public boolean delete(String name, String group)  {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(name, group); //通过触发器名和组名获取TriggerKey
            JobKey jobKey = JobKey.jobKey(name, group);//通过任务名和组名获取JobKey
            scheduler.pauseTrigger(triggerKey); // 停止触发器
            scheduler.unscheduleJob(triggerKey);// 移除触发器
            scheduler.deleteJob(jobKey); // 删除任务
        } catch (Exception e){
            System.out.println(e);
        }
        return true;
    }

    /**
     * @Author : maichaojiu
     * @Description : 修改定时任务时间
     * Date : 2018/4/8 14:33
     */
    public boolean modify(String name, String group, String cron) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(name, group);//通过触发器名和组名获取TriggerKey
            CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey);//通过TriggerKey获取CronTrigger
            if (trigger == null)  return true;
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cron)) {
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(trigger.getCronExpression());
                trigger = (CronTrigger)trigger.getTriggerBuilder()//重新构建trigger
                        .withIdentity(triggerKey)
                        .withSchedule(scheduleBuilder)
                        .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                        .build();
                scheduler.rescheduleJob(triggerKey, trigger);//按新的trigger重新设置job执行
            }
        } catch (Exception e){
            System.out.println(e);
        }

        return true;
    }
}
